本文转自
简书 - [阿策神奇] - Flutter 61: 图解基本 Button 按钮小结 (一)
简书 - [阿策神奇] - Flutter 62: 图解基本 Button 按钮小结 (二)
本站个人笔记本使用,还请大家移步关注原作者。
此处只作备份,以防止作者删除。
Button
在日常中是必不可少的,小菜尝试过不同类型的 Button
,也根据需求自定义过,今天小菜系统的学习一下最基本的 Button
;
Flutter
中没有 Button Widget
,但提供了很多不同类型的 Child Button Widget
;小菜分析源码整体可分为 RawMaterialButton
和 IconButton
两类;
其中 RaisedButton / FlatButton / OutlineButton
继承自 MaterialButton
且 MaterialButton
是对 RawMaterialButton
的封装;而BackButton / CloseButton / PopupMenuButton
继承自 IconButton
;最终 RawMaterialButton
和 IconButton
都是由 ConstrainedBox
填充绘制;
lixyz 按:按照原作者的说法,BackButton 等是 IconButton 的子类,但是通过查看源码发现 BackButton 是
BackButton extends StatelessWidget
,究竟是怎么 回事儿呢?
原因是这样的,看 BackButton 的源码:
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
return IconButton(
icon: const BackButtonIcon(),
color: color,
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
onPressed: () {
Navigator.maybePop(context);
},
);
}
可以看到,build 方法 返回的还是一个 IconButton,与其说是 IconButton 的子类,不如说是装饰者模式的一个应用。
###IconButton 系列
IconButton
系列属于图标按钮,使用相对简单;其核心是 InkResponse
水波纹效果;
#####源码分析
xxxxxxxxxx
const IconButton({
Key key,
this.iconSize = 24.0, // 图标大小
this.padding = const EdgeInsets.all(8.0), // 图标周围间距
this.alignment = Alignment.center, // 图标位置
this.icon, // 图标资源
this.color, // 图标颜色
this.highlightColor, // 点击高亮颜色
this.splashColor, // 水波纹颜色
this.disabledColor, // 不可点击时高亮颜色
this.onPressed,
this.tooltip // 长按提示
})
分析源码,其中 icon
和 onPressed
是必须要设置的,其余属性根据需求而适当调整;
小菜首先尝试最基本的 IconButton
;长按会由 tooltip
提醒,点击为默认主题色;
xxxxxxxxxx
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip1',
onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
小菜尝试其中几个属性;其中 icon
颜色为 cyan
,点击高亮背景色为 deepPurple
,水波纹颜色为 redAccent
;注意当 icon
自身设置颜色时 color
属性不生效;
xxxxxxxxxx
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip2',
color: Colors.cyan,
highlightColor: Colors.deepPurple.withOpacity(0.4),
splashColor: Colors.redAccent,
onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
小菜尝试不可点击时,icon
颜色为 disabledColor
设置的 green
;同样若 icon
本身设置了颜色,disabledColor
不生效;注意:onPressed: null
与 onPressed: ()=> null
不同,前者代表无点击事件;后者代表有点击事件,只是点击无操作;
xxxxxxxxxx
IconButton(icon: Icon(Icons.android), disabledColor: Colors.green, onPressed: null);
icon
为 Widget
采用 Icon / Image / ImageIcon 等
均可;
xxxxxxxxxx
IconButton(icon: Image.asset('images/ic_launcher.png'), iconSize: 40.0, onPressed: null);
BackButton
作用非常明确,一般用作返回上一个页面;
xxxxxxxxxx
const BackButton({ Key key, this.color })
分析源码,BackButton
继承自 IconButton
,只允许设置图标颜色,图标样式 Android
与 iOS
不同且不可修改;点击时会优先判断 maybePop
是否可以返回上一页;
xxxxxxxxxx
BackButton();
BackButton(color: Colors.green);
CloseButton
一般用作导航栏关闭按钮与 BackButton
类似;
xxxxxxxxxx
const CloseButton({ Key key }) : super(key: key);
分析源码,CloseButton
继承自 IconButton
,无需设置任何属性;点击时会优先判断 maybePop
是否可以返回上一页;
#####案例尝试
xxxxxxxxxx
CloseButton();
RawMaterialButton
是 MaterialButton
的基础,核心是由 Material
和 InkWell
等组成;但不可用当前 Theme
或 ButtonTheme
来计算未指定参数的默认值;
xxxxxxxxxx
const RawMaterialButton({
Key key,
this.onPressed,
this.onHighlightChanged, // 高亮变化的回调
this.textStyle, // 文字属性
this.fillColor, // 填充颜色
this.highlightColor, // 背景高亮颜色
this.splashColor, // 水波纹颜色
this.elevation = 2.0, // 阴影
this.highlightElevation = 8.0, // 高亮时阴影
this.disabledElevation = 0.0, // 不可点击时阴影
this.padding = EdgeInsets.zero, // 内容周围边距
this.constraints = const BoxConstraints(minWidth: 88.0, minHeight: 36.0), // 默认按钮尺寸
this.shape = const RoundedRectangleBorder(), // 形状样式
this.animationDuration = kThemeChangeDuration, // 动画效果持续时长
this.clipBehavior = Clip.none, // 抗锯齿剪切效果
MaterialTapTargetSize materialTapTargetSize, // 点击目标的最小尺寸
this.child,
})
分析源码可知,RawMaterialButton
没有设置宽高的属性,可根据 padding
或外层依赖 Container
适当调整位置和大小;默认最小尺寸为 88px \* 36px
;
小菜定义了一个基本的按钮,并监听其高亮改变时状态,与我们常见的按钮基本一致;
xxxxxxxxxx
RawMaterialButton(
padding: EdgeInsets.all(20.0),
child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
Padding(child: Icon(Icons.android), padding: EdgeInsets.only(right: 10.0)),
Text('RawMaterialButton', style: TextStyle(color: Colors.brown))
]),
textStyle: TextStyle(color: Colors.pink, fontSize: 18.0),
fillColor: Colors.greenAccent.withOpacity(0.4),
highlightColor: Colors.cyan,
splashColor: Colors.deepPurple.withOpacity(0.4),
onPressed: () => Toast.show('RawMaterialButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
onHighlightChanged: (state) => Toast.show('onHighlightChanged -> $state', context, duration: Toast.LENGTH_SHORT, gravity: Toast.CENTER))
FloatingActionButton
是 RawMaterialButton
的封装,主要用于浮动在屏幕内容之上,一般是位于底部左右角或中间;一般一个页面只有一个;
xxxxxxxxxx
const FloatingActionButton({
Key key,
this.child,
this.tooltip, // 长按提醒
this.foregroundColor, // 按钮上子元素颜色
this.backgroundColor, // 背景色
this.heroTag = const _DefaultHeroTag(), // Hero 动画标签
this.elevation = 6.0, // 阴影
this.highlightElevation = 12.0, // 高亮时阴影
this.onPressed,
this.mini = false, // 尺寸大小,分为 mini 和 default
this.shape = const CircleBorder(), // 样式形状
this.clipBehavior = Clip.none, // 抗锯齿剪切效果
this.materialTapTargetSize, // 点击目标的最小尺寸
this.isExtended = false, // 是否采用 .extended 方式
})
小菜尝试一个基本的 FloatingActionButton
;长按会有 tooltip
提示;
xxxxxxxxxx
floatingActionButton: FloatingActionButton(child: Icon(Icons.android), tooltip: 'FloatingActionButton ToolTip',
onPressed: () => Toast.show('FloatingActionButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
foregroundColor
为按钮上层子元素颜色,若子元素本身设置颜色则不生效;backgroundColor
为按钮背景色;
xxxxxxxxxx
foregroundColor: Colors.redAccent.withOpacity(0.7),
backgroundColor: Colors.green.withOpacity(0.4),
elevation
按钮默认阴影高度,即 z
轴高度;highlightElevation
为点击高亮时阴影高度;
xxxxxxxxxx
elevation: 0.0,
highlightElevation: 10.0,
mini
是否展示成小尺寸模式;materialTapTargetSize
为配置目标的最小点击尺寸,padded
为默认的 48px \* 48px
为 Android
推荐尺寸;shrinkWrap
为缩小到 Material
提供的最小尺寸;
xxxxxxxxxx
mini: true,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape
为样式尺寸;clipBehavior
为抗锯齿效果;
xxxxxxxxxx
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(14.0))),
clipBehavior: Clip.antiAlias,
heroTag
动画标签,默认的是 FloatingActionButtonAnimator.scaling
;且 heroTag
默认是相同的,可以自定义为唯一标签;小菜设置上一页面与当前页面 FloatingActionButton
的 heroTag
相同;
xfloatingActionButtonAnimator: MyAnimation(),
heroTag: "aceTag",
class MyAnimation extends FloatingActionButtonAnimator {
double _x, _y;
Offset getOffset({Offset begin, Offset end, double progress}) {
_x = begin.dx + (end.dx - begin.dx) * progress;
_y = begin.dy + (end.dy - begin.dy) * progress;
return Offset(_x * 0.5, _y * 0.9);
}
Animation<double> getRotationAnimation({Animation<double> parent}) {
return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
}
Animation<double> getScaleAnimation({Animation<double> parent}) {
return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
}
}
FloatingActionButton
提供了 .extended
方式创建代表标签样式的,非正方形的按钮样式;其余属性无差;
xxxxxxxxxx
floatingActionButton: FloatingActionButton.extended(
onPressed: () => Toast.show('FloatingActionButton.extended', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
icon: Icon(Icons.android),
label: Text('Android'));
针对特殊的个性化,FloatingActionButton
展示的大小可能会有所不同;小菜尝试了几种方式;
通过最基本的 RawMaterialButton
实现 FloatingActionButton
样式,外层添加 Container
约束大小;小菜比较推荐方式一,灵活性更高;
xxxxxxxxxx
// 方式一
floatingActionButton: Container(
width: 100.0, height: 100.0,
color: Colors.greenAccent.withOpacity(0.4),
child: RawMaterialButton(
shape: CircleBorder(),
elevation: 0.0,
child: Icon(Icons.android),
onPressed: () {}))
借助 FittedBox
将按钮整体放大到 Container
约束范围内;
xxxxxxxxxx
// 方式二
floatingActionButton: Container(
width: 100.0, height: 100.0,
child: FittedBox(
child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {})))
SizeBox
与 FittedBox
约束方式不同,只是整体范围变大,其内部按钮按 Material
建议样式展示;
xxxxxxxxxx
// 方式三
floatingActionButton: SizedBox(
width: 100.0, height: 100.0,
child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))
scale
与 FittedBox
类似,按比例缩放;
xxxxxxxxxx
// 方式四
floatingActionButton: Transform.scale(
scale: 1.5,
child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))
xxxxxxxxxx
const MaterialButton({
Key key,
this.onPressed,
this.onHighlightChanged, // 高亮变化的回调
this.textTheme, // 文字主题
this.textColor, // 文字颜色
this.disabledTextColor, // 不可点击时文字颜色
this.color, // 背景色
this.disabledColor, // 不可点击时背景色
this.highlightColor, // 点击高亮时背景色
this.splashColor, // 水波纹颜色
this.colorBrightness,
this.elevation, // 阴影高度
this.highlightElevation, // 高亮时阴影高度
this.disabledElevation, // 不可点击时阴影高度
this.padding, // 内容周围边距
this.shape, // 按钮样式
this.clipBehavior = Clip.none, // 抗锯齿剪切效果
this.materialTapTargetSize, // 点击目标的最小尺寸
this.animationDuration, // 动画效果持续时长
this.minWidth, // 最小宽度
this.height, // 按钮高度
this.child,
})
分析源码可知,MaterialButton
作为其他 Button
父类,各属性比较清晰明了,有 hight
属性可设置 Button
高度,其子类 Button
只可通过 padding
或其他方式调整高度;
小菜测试发现 hight
可以设置 MaterialButton
高度,但 shape
按钮形状却不适用;其父类 RawMaterialButton
却正常;小菜尝试网上大神的处理方式是外层依赖 Material
并需要 clip
裁切成 shape
样式;有待进一步学习;
xxxxxxxxxx
Material(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
clipBehavior: Clip.antiAlias,
child: MaterialButton(
color: Colors.teal.withOpacity(0.4),
height: 60.0,
child: Text('MaterialButton'),
onPressed: () {}))
xxxxxxxxxx
const RaisedButton({
Key key,
VoidCallback onPressed,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme, // 按钮文字主题
Color textColor, // 子元素颜色
Color disabledTextColor, // 不可点击时子元素颜色
Color color, // 按钮背景色
Color disabledColor, // 不可点击时按钮背景色
Color highlightColor, // 点击高亮时按钮背景色
Color splashColor, // 水波纹颜色
Brightness colorBrightness, // 颜色对比度
double elevation, // 阴影高度
double highlightElevation, // 高亮时阴影高度
double disabledElevation, // 不可点击时阴影高度
EdgeInsetsGeometry padding, // 子元素周围边距
ShapeBorder shape, // 按钮样式
Clip clipBehavior = Clip.none, // 抗锯齿剪切效果
MaterialTapTargetSize materialTapTargetSize,
Duration animationDuration, // 动画时长
Widget child,
})
const FlatButton({
Key key,
VoidCallback onPressed,
ValueChanged<bool> onHighlightChanged,
ButtonTextTheme textTheme, // 按钮文字主题
Color textColor, // 子元素颜色
Color disabledTextColor, // 不可点击时子元素颜色
Color color, // 按钮背景色
Color disabledColor, // 不可点击时按钮背景色
Color highlightColor, // 点击高亮时按钮背景色
Color splashColor, // 水波纹颜色
Brightness colorBrightness, // 颜色对比度
EdgeInsetsGeometry padding, // 子元素周围边距
ShapeBorder shape, // 按钮样式
Clip clipBehavior = Clip.none, // 抗锯齿剪切效果
MaterialTapTargetSize materialTapTargetSize,
Widget child,
})
分析源码可知,RaisedButton
与 FlatButton
基本完全相同,只是 RaisedButton
多了一些阴影高度的特有属性,小菜准备同时对两类 Button
进行尝试,比较两者的不同;
小菜首先尝试最基本的 RaisedButton / FlatButton
可点击和不可点击样式;
xxxxxxxxxx
// 可点击
RaisedButton(child: Text('RaisedButton'), onPressed: () => Toast.show('RaisedButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
FlatButton(child: Text('FlatButton'), onPressed: () => Toast.show('FlatButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
// 不可点击
RaisedButton(child: Text('RaisedButton'), onPressed: null)
FlatButton(child: Text('FlatButton'), onPressed: null)
ButtonTextTheme
为默认子元素主题,可以设置基本的三种主题样式:nomal
对应 [ThemeData.brightness]
;primary
对应 [ThemeData.primaryColor]
;accent
对应 [ThemeData.accentColor]
;展示效果比较明显;
xxxxxxxxxx
RaisedButton(child: Text('R.nomal'), textTheme: ButtonTextTheme.normal, onPressed: () => Toast.show('RaisedButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
RaisedButton(child: Text('R.primary'), textTheme: ButtonTextTheme.primary, onPressed: () => Toast.show('RaisedButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
RaisedButton(child: Text('R.accent'), textTheme: ButtonTextTheme.accent, onPressed: () => Toast.show('RaisedButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
FlatButton(child: Text('F.nomal'), textTheme: ButtonTextTheme.normal, onPressed: () => Toast.show('FlatButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
FlatButton(child: Text('F.primary'), textTheme: ButtonTextTheme.primary, onPressed: () => Toast.show('FlatButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
FlatButton(child: Text('F.accent'), textTheme: ButtonTextTheme.accent, onPressed: () => Toast.show('FlatButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
OutlineButton(child: Text('O.nomal'), textTheme: ButtonTextTheme.normal, onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
OutlineButton(child: Text('O.primary'), textTheme: ButtonTextTheme.primary, onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
OutlineButton(child: Text('O.accent'), textTheme: ButtonTextTheme.accent, onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
textColor
为子 Widget
中元素颜色,不仅为文字颜色;disabledTextColor
为不可点击时子 Widget
元素颜色;splashColor
为点击时水波纹颜色;
xxxxxxxxxx
// 可点击
RaisedButton(child: Row(mainAxisSize: MainAxisSize.min,
children: <Widget>[ Padding(child: Icon(Icons.ac_unit), padding: EdgeInsets.only(right: 10.0)), Text('RaisedButton') ]),
textColor: Colors.deepPurple, onPressed: () => {})
FlatButton(child: Row(mainAxisSize: MainAxisSize.min,
children: <Widget>[ Padding(child: Icon(Icons.ac_unit), padding: EdgeInsets.only(right: 10.0)), Text('FlatButton') ]),
textColor: Colors.deepPurple, onPressed: () => {})
// 不可点击
RaisedButton(child: Row(mainAxisSize: MainAxisSize.min,
children: <Widget>[ Padding(child: Icon(Icons.ac_unit), padding: EdgeInsets.only(right: 10.0)), Text('RaisedButton') ]),
textColor: Colors.deepPurple, onPressed: null)
FlatButton(child: Row(mainAxisSize: MainAxisSize.min,
children: <Widget>[ Padding(child: Icon(Icons.ac_unit), padding: EdgeInsets.only(right: 10.0)), Text('FlatButton') ]),
textColor: Colors.deepPurple, onPressed: null)
color
为 Button
背景色;highlightColor
为点击时高亮背景色;disabledColor
为不可点击时背景色;
xxxxxxxxxx
// 可点击
RaisedButton(child: Text('RaisedButton'), onPressed: () => {},
color: Colors.green.withOpacity(0.4), highlightColor: Colors.purple.withOpacity(0.4),
splashColor: Colors.yellow.withOpacity(0.7))
FlatButton(child: Text('FlatButton'), onPressed: () => {},
color: Colors.green.withOpacity(0.4), highlightColor: Colors.purple.withOpacity(0.4),
splashColor: Colors.yellow.withOpacity(0.7))
// 不可点击
RaisedButton(child: Text('RaisedButton'), onPressed: null, disabledColor: Colors.red.withOpacity(0.4))
FlatButton(child: Text('FlatButton'), onPressed: null, disabledColor: Colors.red.withOpacity(0.4),)
shape
为 Button
形状;因按钮没有 Material
中 hight
属性,需要采用 padding
或外层依赖其他 Widget
调整按钮大小;
xxxxxxxxxx
RaisedButton(child: Text('RaisedButton'), onPressed: () => {}
padding: EdgeInsets.all(16.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(30.0))))
FlatButton(child: Text('FlatButton'), onPressed: () => {}
padding: EdgeInsets.all(16.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(30.0))))
colorBrightness
代表颜色对比度,一般分为 light / dark
两种;一般时深色的背景需要浅色的文字对比,浅色的背景需要深色的文字对比;
xxxxxxxxxx
// 可点击
RaisedButton(child: Text('R.light'), colorBrightness: Brightness.light, onPressed: () => {})
RaisedButton(child: Text('R.dark'), colorBrightness: Brightness.dark, onPressed: () => {})
FlatButton(child: Text('F.light'), colorBrightness: Brightness.light, onPressed: () => {})
FlatButton(child: Text('F.dark'), colorBrightness: Brightness.dark, onPressed: () => {})
// 不可点击
RaisedButton(child: Text('R.light'), colorBrightness: Brightness.light, onPressed: null)
RaisedButton(child: Text('R.dark'), colorBrightness: Brightness.dark, onPressed: null)
FlatButton(child: Text('F.light'), colorBrightness: Brightness.light, onPressed: null)
FlatButton(child: Text('F.dark'), colorBrightness: Brightness.dark, onPressed: null)
RaisedButton / FlatButton
均提供了 .icon
带图标的简单方式,icon / label
两个属性是必须属性;注意,.icon
方式中 RaisedButton
没有 padding
属性;
xxxxxxxxxx
RaisedButton.icon(icon: Icon(Icons.ac_unit), label: Text('RaisedButton'),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(30.0))), onPressed: () => {})
FlatButton.icon(icon: Icon(Icons.ac_unit), label: Text('FlatButton'),
padding: EdgeInsets.all(16.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(30.0))), onPressed: () => {})
xxxxxxxxxx
const OutlineButton({
Key key,
VoidCallback onPressed,
ButtonTextTheme textTheme, // 按钮文字主题
Color textColor, // 文字颜色
Color disabledTextColor, // 不可点击时文字颜色
Color color, // 按钮背景色
Color highlightColor, // 高亮时颜色
Color splashColor, // 水波纹颜色
double highlightElevation, // 高亮时阴影高度
this.borderSide, // 边框样式
this.disabledBorderColor, // 不可点击时边框颜色
this.highlightedBorderColor, // 高亮时边框颜色
EdgeInsetsGeometry padding, // 内容周围边距
ShapeBorder shape, // 按钮样式
Clip clipBehavior = Clip.none, // 抗锯齿剪切效果
Widget child,
})
分析源码可知,OutlineButton
与其他两种按钮略有不同,强调边框的样式属性且无长按的 tooltip
属性;
小菜首先尝试一个最基本的 OutlineButton
;长按无提醒;
xxxxxxxxxx
OutlineButton(child: Text('OutlineButton'), onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
小菜尝试与其他按钮相同的几类按钮属性,使用方式相同;
xxxxxxxxxx
OutlineButton(
child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
Padding(child: Icon(Icons.ac_unit), padding: EdgeInsets.only(right: 10.0)),
Text('OutlineButton')
]),
textColor: Colors.pink,
disabledTextColor: Colors.green,
padding: EdgeInsets.all(20.0),
color: Colors.blueAccent.withOpacity(0.2),
highlightColor: Colors.amber,
borderSide: BorderSide(width: 4.0),
highlightedBorderColor: Colors.brown,
disabledBorderColor: Colors.greenAccent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(50.0))),
clipBehavior: Clip.none,
onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
以下为 OutlineButton
特有属性:borderSide
代表边框样式;disabledBorderColor
代表不可点击时边框颜色;highlightedBorderColor
代表高亮时边框颜色;其中 borderSide
可以设置边框颜色宽度及样式(solid / none
);
xxxxxxxxxx
OutlineButton(child: Text('OutlineButton'),
borderSide: BorderSide(width: 4.0, color: Colors.deepPurple, style: BorderStyle.solid),
highlightedBorderColor: Colors.teal,
onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
OutlineButton(child: Text('OutlineButton'),
borderSide: BorderSide(width: 4.0, color: Colors.deepPurple, style: BorderStyle.solid),
disabledBorderColor: Colors.redAccent,
onPressed: null)
OutlineButton
还提供了 .icon
带图标的简单方式,icon / label
两个属性是必须属性;
xxxxxxxxxx
OutlineButton.icon(
icon: Icon(Icons.ac_unit),
label: Text('OutlineButton'),
textColor: Colors.pink,
disabledTextColor: Colors.green,
padding: EdgeInsets.all(20.0),
color: Colors.blueAccent.withOpacity(0.2),
highlightColor: Colors.amber,
borderSide: BorderSide(width: 4.0),
highlightedBorderColor: Colors.brown,
disabledBorderColor: Colors.greenAccent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(50.0))),
clipBehavior: Clip.none,
onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
小菜原来以为按钮的子元素是 Widget
,可自由设置各类效果,单独的 textColor
是否会略显多余;可实际并非如此,子元素设置颜色等之后 textColor
不生效;但 textColor
与主题相关;小菜以 OutlineButton
为例,一目了然;
xxxxxxxxxx
// Text 设置颜色
OutlineButton(
child: Text('OutlineButton', style: TextStyle(color: Colors.deepPurple)),
onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
// textColor 设置颜色
OutlineButton(
child: Text('OutlineButton'), textColor: Colors.deepPurple,
onPressed: () => Toast.show('OutlineButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM))
使用 RaisedButton
时会自带阴影效果,阴影的高度和高亮时的阴影高度均可自由设置;但是阴影的颜色应该如何处理呢,官方暂未提供阴影效果属性;小菜尝试了网上大神的方式,RaisedButton
外层依赖带模糊阴影效果的 Container
;小菜借鉴并稍微调整一下,解决方案并非最佳,仅作尝试;
初始时定义一个默认的高度 height
作为阴影高度,监听按钮的 onHighlightChanged
方法更改 height
高度作为高亮时阴影高度;
建议:
使用高亮颜色时 highlightElevation
建议设置为 0.0
;
若按钮有样式设置,依赖的 Container
也要设置相同的 shape
样式;
xxxxxxxxxx
var height = 5.0;
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.red.withOpacity(0.2),
blurRadius: hight,
offset: Offset(0, hight))
]),
child: RaisedButton(
child: Text('RaisedButton'),
padding: EdgeInsets.symmetric(vertical: 15.0),
highlightElevation: 0.0,
onHighlightChanged: (state) {
setState(() {
hight = (state) ? 20.0 : 5.0;
});
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
onPressed: () => {}))